<template>
  <div class="fs-container">
    <Driver v-if="isLogin" />

    <n-layout has-sider>
      <n-layout-sider
        collapse-mode="transform"
        :collapsed-width="50"
        :width="200"
        show-trigger="arrow-circle"
        content-style="padding: 24px;"
        class="left-container"
        :show-collapsed-content="false"
        bordered
      >
        <div class="title">上级目录列表</div>
        <div class="dir-list">
          <n-tabs ref="tabsRef" placement="left" :on-before-leave="tabChange"
                  :default-value="currTabValue" v-model:value="currTabValue">
            <n-tab v-for="folder in currentDirInfo?.parentFolders"
                   :key="folder.id" :name="folder.name">
              <n-button text>
                <template #icon>
                  <n-icon>
                    <FolderOpenOutline />
                  </n-icon>
                </template>
                <n-ellipsis style="max-width: 95px">
                  {{ folder.name }}
                </n-ellipsis>
              </n-button>
            </n-tab>
          </n-tabs>
        </div>
      </n-layout-sider>
      <n-layout-content content-style="padding: 24px;" class="right-container">
        <div class="title">
          <n-space justify="space-between">
            <n-breadcrumb separator=">">
              <n-breadcrumb-item v-for="(breadcrumb, index) in breadcrumbs" :key="breadcrumb.id"
                                 @click="changeDir(breadcrumb.id, index)">
                {{ breadcrumb.name }}
              </n-breadcrumb-item>
            </n-breadcrumb>
            <n-tag :bordered="false" type="success">
              权限: {{ converterPower2DescName(currentDirInfo?.folder.power) }}
            </n-tag>
          </n-space>
        </div>
        <div class="expansion">
          <n-space justify="space-between" size="large">
            <n-space size="large">
              <!-- 批量操作按钮: 下载、删除、拷贝、移动 -->
              <n-dropdown :options="batchOptions" trigger="click">
                <n-button type="warning" text>
                  <template #icon>
                    <GoldOutlined />
                  </template>
                  批量 ▼
                </n-button>
              </n-dropdown>
            </n-space>
            <n-space size="large">
              <n-space size="large">
                <n-button type="info" secondary strong circle v-debounce="toHashAndLoadingData">
                  <template #icon><Refresh/></template>
                </n-button>
              </n-space>
              <!-- 操作按钮: 上传、创建 -->
              <n-dropdown :options="controlOptions" v-if="isLogin && isUser(showStatus)" trigger="click">
                <n-button type="primary" text>
                  <template #icon>
                    <SettingsOutline />
                  </template>
                  操作 ▼
                </n-button>
              </n-dropdown>
              <!-- 切换权限 -->
              <n-select v-if="isLogin" v-model:value="showStatus" :options="showStatusOptions"
                        size="small" status="error" :show-checkmark="false"/>
              <!-- 登录按钮-->
              <n-button text type="error" v-else @click="() => router.replace('/login')">
                <template #icon>
                  <LoginOutlined />
                </template>
                前往登录
              </n-button>
            </n-space>
          </n-space>
        </div>
        <div class="content">
          <!-- 文件上传组件、表格展示 -->
          <uploader :options="uploaderOptions"
                    :auto-start="false"
                    @files-added="onFilesAdded"
                    @file-success="onFileSuccess"
                    @file-error="onFileError"
                    @file-progress="onFileProgress">
            <uploader-unsupport></uploader-unsupport>
            <uploader-btn id="upload-btn" ref="selectFileBtnRef">选择文件</uploader-btn>
            <uploader-drop id="upload-drop">
              <n-data-table
                :bordered="false"
                :columns="columns"
                :data="tableData"
                :row-props="rowProps"
                :loading="tableLoading"
                :checked-row-keys="checkedRowKeys"
                :rowKey="row => row.id"
                @update:checked-row-keys="checkedHandler"
                :style="{height: contentHeight}"
                :scroll-x="600"
                flex-height
              />

              <!-- 文件上传下载按钮 -->
              <n-button-group class="file_load_list_btn">
                <!-- 文件上传列表弹窗 -->
                <n-popconfirm
                  v-if="isLogin"
                  display-directive="show"
                  :positive-text="null"
                  :negative-text="null"
                  :show-icon="false">
                  <template #trigger>
                    <n-button ref="uploadBtnRef" type="error" round>
                      <template #icon>
                        <CloudUploadOutline />
                      </template>
                    </n-button>
                  </template>
                  <n-card class="file-list-card">
                    <uploader-list style="height: 100%">
                      <template v-slot="data">
                        <ul class="file-list-ul">
                          <li v-for="file in data.fileList" :key="file.id">
                            <uploader-file :file="file" :list="true"></uploader-file>
                          </li>
                        </ul>
                        <div class="no-file" v-if="!data.fileList.length">
                          暂无待上传文件
                        </div>
                      </template>
                    </uploader-list>
                  </n-card>
                </n-popconfirm>
                <!-- 文件下载列表弹窗 -->
                <n-popconfirm
                  display-directive="show"
                  :positive-text="null"
                  :negative-text="null"
                  :show-icon="false">
                  <template #trigger>
                    <n-button ref="downloadBtnRef" type="info" icon-placement="right" round>
                      <template #icon>
                        <CloudDownloadOutline />
                      </template>
                    </n-button>
                  </template>
                  <n-card class="file-list-card">
                    <ul class="file-list-ul">
                      <li class="download-li" v-for="(dataMap, index) in downloadMap" :key="dataMap[0]">
                        <div style="width: 95%; display: flex; flex-direction: column">
                          <span style="font-size: 16px">{{ dataMap[1].name }}</span>
                          <n-progress
                            type="line"
                            :percentage="dataMap[1].progress"
                            :indicator-placement="'inside'"
                            processing
                          />
                        </div>
                        <div style="line-height: 50px; padding: 0 5px">
                          <n-button text @click="() => {
                            dataMap[1].control.abort();
                            fileSystemStore.closeDownloadTask(dataMap[1].id);
                            message.info(`取消文件[${dataMap[1].name}]下载`)
                          }">
                            <template #icon>
                              <CloseCircleOutline />
                            </template>
                          </n-button>
                        </div>
                      </li>
                    </ul>
                    <div class="no-file" v-if="!downloadMap.size">
                      暂无下载文件
                    </div>
                  </n-card>
                </n-popconfirm>
              </n-button-group>
            </uploader-drop>
          </uploader>
        </div>
      </n-layout-content>
    </n-layout>

    <!-- 文件夹下拉菜单 -->
    <n-dropdown
      :animated="false"
      placement="bottom-start"
      trigger="manual"
      :x="xRef"
      :y="yRef"
      :options="dirOptions"
      :show="showDirDropdownRef"
      :on-clickoutside="() => showDirDropdownRef = false"
      @select="dirSelect"
    />

    <!-- 文件下拉菜单 -->
    <n-dropdown
      :animated="false"
      placement="bottom-start"
      trigger="manual"
      :x="xRef"
      :y="yRef"
      :options="fileOptions"
      :show="showFileDropdownRef"
      :on-clickoutside="() => showFileDropdownRef = false"
      @select="fileSelect"
    />

    <!-- 进行文件夹新增/修改信息的Model -->
    <n-modal
      v-model:show="optionalModelDetails.show"
      style="width: 400px"
      preset="card"
      :title="optionalModelDetails.title[optionalModelDetails.type]"
      size="small"
      :bordered="false"
    >
      <n-space justify="center" size="large" vertical>
        <n-tag type="info" v-if="optionalModelDetails.type">
          <n-ellipsis style="max-width: 300px">
            源: {{ optionalModelDetails.type > 2 ? optionalModelDetails.formData.name : currentRow.name }}
          </n-ellipsis>
        </n-tag>

        <n-input-group v-if="optionalModelDetails.type < 2">
          <n-input-group-label>文件夹名称</n-input-group-label>
          <n-input @keyup.enter="optionSubmit" :style="{ width: '43%' }" v-model:value="optionalModelDetails.formData.name" />
          <n-select :style="{ width: '23%' }" v-model:value="optionalModelDetails.formData.power" :options="dirPowerOptions" />
        </n-input-group>

        <n-input-group v-if="optionalModelDetails.type === 2">
          <n-input-group-label>文件名称</n-input-group-label>
          <n-input @keyup.enter="optionSubmit" v-model:value="optionalModelDetails.formData.name" />
        </n-input-group>

        <n-input-group v-if="optionalModelDetails.type > 2">
          <n-input-group-label>将{{ optionalModelDetails.title[optionalModelDetails.type] }}到</n-input-group-label>
          <n-tree-select
            v-if="optionalModelDetails.type > 2"
            key-field="id"
            label-field="name"
            :options="dirChangeOptions"
            :default-value="currentRow?.fileParentFolder"
            :default-expanded-keys="['ROOT', currentDirInfo?.folder.parentFolder]"
            @update:value="handleUpdateValue"
          />
        </n-input-group>
      </n-space>

      <template #action>
        <n-button type="primary" v-throttle="optionSubmit"
                  style="float: right">
          提交
        </n-button>
      </template>
    </n-modal>

    <!-- 表格额外操作栏
    <div v-show="rowDetails.show"
         :style="rowDetails.style"
         class="menu-bar">
      <n-button @click="handler(rowDetails.data)">点击</n-button>
    </div>-->
  </div>
</template>

<script setup lang="ts">
import {nextTick, onMounted, onUnmounted, reactive, ref, watch} from 'vue';
import {storeToRefs} from "pinia";
import {useRoute, useRouter} from "vue-router";
import {NButton, NIcon, useDialog, useMessage} from 'naive-ui';
import Driver from '@/components/Driver/Driver.vue';
// @ts-ignore
import {
  CloseCircleOutline,
  CloudDownloadOutline,
  CloudUploadOutline,
  FolderOpenOutline,
  MoveOutline,
  ReceiptOutline,
  Repeat,
  SettingsOutline,
  Refresh
} from '@vicons/ionicons5';
import {
  CloudDownloadOutlined,
  CloudUploadOutlined,
  CopyOutlined,
  DeleteOutlined,
  EditOutlined,
  EyeOutlined,
  FolderAddOutlined,
  FolderViewOutlined,
  GoldOutlined,
  LoginOutlined,
  MoreOutlined,
  RestOutlined,
  RetweetOutlined,
  UndoOutlined,
  VerticalLeftOutlined
} from "@vicons/antd";
import {
  createFolder,
  delete2Recycle,
  deleteFolder,
  downloadFile,
  fileCopyTo,
  fileMoveTo,
  fileRename,
  getDirInfo,
  getFolderList,
  getPublicDirInfo,
  getRecycleList,
  recycleDelete,
  recycleRestore,
  updateFolder
} from "@/api/worker/fileSystem";
import {fileLoadHelper} from '@/views/worker/fileSystem/uploadOptions';
import {dataTableHelper} from "@/views/worker/fileSystem/dataTable";
import {
  converterPower2DescName,
  IFolder,
  isRecycle,
  isUser,
  Power,
  ShowEnum
} from "@/views/worker/fileSystem/module-type";
import {ResultEnum} from "@/enums/httpEnum";
import {useUserStore} from "@/store/modules/user";
import {useFileSystemStore} from "@/store/modules/fileSystem";
import {getFilePreviewUrl} from "@/api/system/config";
import {renderIcon} from "@/utils";
import download from "downloadjs";
import {encodePreviewUrl, generatorApiUrl, getRootUrl} from "@/utils/urlUtils";

const userStore = useUserStore()
const message = useMessage()
const dialog = useDialog()
const fileSystemStore = useFileSystemStore()
const route = useRoute()
const router = useRouter()

// 获取当前的目录id
const getCurrentDirId = () => window.location.hash ? window.location.hash.slice(1) : null

const showStatus = ref(route.path === '/files' ? ShowEnum.PUBLIC : ShowEnum.USER);
const isLogin = ref(userStore.getToken !== '');
watch(() => showStatus.value, () => toHashAndLoadingData('ROOT'), { deep: true })
const showStatusOptions = [
  {
    label: '公共',
    value: ShowEnum.PUBLIC
  },
  {
    label: '用户',
    value: ShowEnum.USER
  },
  {
    label: '回收站',
    value: ShowEnum.RECYCLE
  },
]

const { downloadMap } = storeToRefs(fileSystemStore)
const filePreviewUrl = ref<string>()

const currentDirInfo = ref()
const currTabValue = ref()
const currentRow = ref<any>({})
const breadcrumbs = ref()
const toHashAndLoadingData = async (to: string | null = null) => {
  // 加载数据
  const loadDataList = async (id: string) => {
    let res;
    switch (showStatus.value) {
      case ShowEnum.PUBLIC:
        res = await getPublicDirInfo(id);
        break;
      case ShowEnum.USER:
        res = await getDirInfo(id);
        break;
      case ShowEnum.RECYCLE:
        res = await getRecycleList();
        break;
      default:
        res = await getPublicDirInfo(id);
        break;
    }
    currentDirInfo.value = res
    breadcrumbs.value = res.path
    currTabValue.value = res.path[res.path.length - 1].name
    tableData.value = [
      ...res.folders,
      ...res.files
    ]
    dirPowerOptions.value = generatorDirPowerOptions()
    controlOptions.value = generatorControlOptions()
    batchOptions.value = generatorBatchOptions()
    // 解决标签页指向问题
    await nextTick(() => tabsRef.value?.syncBarPosition())
  }
  try {
    tableLoading.value = true
    let hash = getCurrentDirId();
    if (!hash) {
      let toHome = 'ROOT';
      history.pushState({}, '', `${route.path}#${toHome}`)
      return await loadDataList(toHome)
    }
    if (to) {
      history.pushState({}, '', `${route.path}#${to}`)
      return await loadDataList(to)
    }
    return await loadDataList(hash)
  } catch (e) {
    if (isRecycle(showStatus.value)) {
      showStatus.value = ShowEnum.USER;
      return toHashAndLoadingData('ROOT')
    }
    // @ts-ignore
    if (!e?.message.startsWith('登录')) {
      return toHashAndLoadingData('ROOT')
    }
  } finally {
    tableLoading.value = false
  }
}
const contentHeight = ref('200px')
const resizeHandler = () => {
  let number = document.body.clientHeight - 64 - 44 - 10 - 170;
  contentHeight.value = `${number < 300 ? 300 : number}px`
}
onMounted(async () => {
  // 如果登陆了就定向到文件系统
  if (route.path === '/files' && isLogin.value) {
    await router.replace(`/worker/fileSystem${route.hash}`)
  }
  await toHashAndLoadingData()
  // 获取文件预览的url
  getFilePreviewUrl().then(res => {
    const { code, data } = res;
    if (code === ResultEnum.SUCCESS) {
      filePreviewUrl.value = data
    }
  })
  window.addEventListener('resize', resizeHandler)
  resizeHandler()
})
onUnmounted(() => {
  window.removeEventListener('resize', resizeHandler)
})

const tabsRef = ref()
const changeDir = (toId, index?) => {
  // 除了最后一个都可以点击
  if (index !== breadcrumbs.value.length - 1) {
    toHashAndLoadingData(toId)
  }
}
const tabChange = async (name: string | number) => {
  await changeDir(currentDirInfo.value?.parentFolders.find(folder => folder.name === name)?.id)
  return true
}

const checkedRowKeys = ref<string[]>([])
// 检验当前选中的是否是当前目录中的文件, 将不是的过滤掉
const checkCheckedRowKeys = () => {
  let change: string[] = []
  // 判断选中的是否是当前文件夹下的文件，如果是才进行选中
  currentDirInfo.value.files.map(file => file.id).forEach(id => {
    if (checkedRowKeys.value.includes(id)) {
      change.push(id)
    }
  })
  checkedRowKeys.value = change
  if (checkedRowKeys.value.length === 0) {
    message.warning('请选择文件')
    throw new Error('请选择文件')
  }
}
const checkedHandler = rowKeys => {
  let change: string[] = []
  // 判断选中的是否是当前文件夹下的文件，如果是才进行选中
  currentDirInfo.value.files.map(file => file.id).forEach(id => {
    if (rowKeys.includes(id)) {
      change.push(id)
    }
  })
  checkedRowKeys.value = change
}

const controlOptions = ref<any[]>([])
const generatorControlOptions = () => {
  // COMMON 目录下不允许上传文件
  const uploadShow = currentDirInfo.value.folder.id !== 'COMMON';
  // COMMON 子目录下的 目录 不能再创建目录
  const createShow = currentDirInfo.value.folder.parentFolder !== 'COMMON';
  return [
    {
      label: '上传文件',
      key: 'uploadFile',
      icon: renderIcon(CloudUploadOutlined),
      show: uploadShow,
      props: {
        onClick: () => {
          selectFileBtnRef.value.$el.click()
        }
      }
    },
    {
      type: 'divider',
      key: 'd1',
      show: uploadShow && createShow
    },
    {
      label: '新建文件夹',
      key: 'createDir',
      icon: renderIcon(FolderAddOutlined),
      show: createShow,
      props: {
        onClick: () => {
          optionalModelDetails.type = 0
          // 如果当前目录是 common 权限, 那么就只能是 common
          if (currentDirInfo.value.folder.power === Power.COMMON) {
            optionalModelDetails.formData.power = Power.COMMON
          } else {
            optionalModelDetails.formData.power = Power.PUBLIC
          }
          optionalModelDetails.formData.name = ''
          optionalModelDetails.show = true
        }
      }
    },
  ]
}

// ------- 通用逻辑
// 处理下载的逻辑
const handlerDownload = row => {
  const ctrl = new AbortController()
  let isStore = fileSystemStore.pushDownloadTask({
    id: row.id,
    name: row.name,
    progress: 0,
    control: ctrl
  })
  if (isStore) {
    message.info('已触发下载，请耐心等待...')
    downloadFile(row.id, ctrl.signal, e => {
      const progress = Math.ceil(e.loaded / e.total * 100)
      fileSystemStore.updateDownloadTask({
        id: row.id,
        name: row.name,
        progress: progress,
        control: ctrl
      })
    }).then(res => {
      download(res.data, row.name, row.type)
    }).finally(() => {
      fileSystemStore.closeDownloadTask(row.id)
    })
  } else {
    downloadBtnRef.value.$el.click()
    message.warning('该文件已在下载队列')
  }
}
// 处理预览的逻辑
const handlerPreview = (row) => {
  // 判断是否为 md 文件
  if (row.name.endsWith('.md')) {
    window.open(`${getRootUrl()}/mdPreview/${row.id}`)
  } else {
    const previewUrl = generatorApiUrl(`/common/preview/${row.id}?fullfilename=${row.name}`)
    if (!filePreviewUrl.value) {
      return message.warning('预览接口尚未接入，请联系管理员')
    }
    window.open(`${filePreviewUrl.value}${encodePreviewUrl(previewUrl)}`)
  }
}

// ------- 文件上传下载帮助
// @ts-ignore
const {
  uploadBtnRef, downloadBtnRef, selectFileBtnRef, options: uploaderOptions,
  onFilesAdded, onFileSuccess, onFileProgress, onFileError
} = fileLoadHelper(getCurrentDirId, toHashAndLoadingData)

// ------- 表格帮助
const dataTableContextmenuEvent = row => {
  return (e) => {
    currentRow.value = row;
    e.preventDefault()
    if (!!currentRow.value?.fileParentFolder) {
      showFileDropdownRef.value = false;
    } else {
      showDirDropdownRef.value = false;
    }
    dirOptions.value = generatorDirOptions()
    fileOptions.value = generatorFileOptions()
    nextTick().then(() => {
      if (!!currentRow.value?.fileParentFolder) {
        showFileDropdownRef.value = true;
      } else {
        showDirDropdownRef.value = true;
      }
      xRef.value = e.clientX
      yRef.value = e.clientY
    })
  }
}
const {
  tableData, columns, tableLoading, rowDetails,
  rowProps, handler
} = dataTableHelper(changeDir, handlerPreview, dataTableContextmenuEvent)

// ------- 文件夹下拉菜单
const xRef = ref(0)
const yRef = ref(0)
const dirOptions = ref<any[]>([])
const showDirDropdownRef = ref(false)
const generatorDirOptions = () => {
  const changeShow = isUser(showStatus.value) && userStore.username === currentRow.value.createUser;
  const deleteShow = isUser(showStatus.value) && userStore.username === currentRow.value.createUser;
  return [
    {
      label: '访问',
      key: 'observer',
      icon: renderIcon(FolderViewOutlined),
      props: {
        onClick: () => toHashAndLoadingData(currentRow.value.id)
      }
    },
    {
      type: 'divider',
      key: 'd1',
      show: changeShow || deleteShow,
    },
    {
      label: '更改',
      key: 'update',
      icon: renderIcon(EditOutlined),
      show: changeShow,
      props: {
        onClick: () => {
          optionalModelDetails.type = 1
          optionalModelDetails.formData.name = currentRow.value.name
          optionalModelDetails.formData.power = currentRow.value.power
          optionalModelDetails.show = true
        }
      }
    },
    {
      label: '删除',
      key: 'delete',
      icon: renderIcon(DeleteOutlined),
      show: deleteShow,
      props: {
        onClick: async () => {
          await deleteFolder(currentRow.value.id)
          await toHashAndLoadingData()
        }
      }
    },
  ]
}
function dirSelect (key, option) {
  showDirDropdownRef.value = false;
}

// ------- 文件下拉菜单
const fileOptions = ref<any[]>([])
const showFileDropdownRef = ref(false)
const generatorFileOptions = () => {
  const user = isLogin.value && isUser(showStatus.value) && userStore.username === currentRow.value.createUser;

  const renameShow = isUser(showStatus.value) && userStore.username === currentRow.value.createUser;
  const moveToShow = user;
  const copyToShow = isLogin.value && !isRecycle(showStatus.value);
  const deleteShow = user;
  const more = moveToShow || copyToShow || deleteShow;
  const recycleShow = isLogin.value && isRecycle(showStatus.value);
  const editorShow = user && currentRow.value?.name.endsWith('.md');
  return [
    {
      label: '下载',
      key: 'download',
      icon: renderIcon(CloudDownloadOutlined),
      show: !isRecycle(showStatus.value),
      props: {
        onClick: () => handlerDownload(currentRow.value),
      }
    },
    {
      label: '预览',
      key: 'preview',
      icon: renderIcon(EyeOutlined),
      show: !isRecycle(showStatus.value),
      props: {
        onClick: () => handlerPreview(currentRow.value),
      }
    },
    {
      type: 'divider',
      key: 'd1',
      show: renameShow || editorShow,
    },
    {
      label: '编辑',
      key: 'editor',
      icon: renderIcon(EditOutlined),
      show: editorShow,
      props: {
        onClick: () => router.replace(`/worker/editor/${currentRow.value.id}`),
      }
    },
    {
      label: '重命名',
      key: 'rename',
      icon: renderIcon(RetweetOutlined),
      show: renameShow,
      props: {
        onClick: () => {
          optionalModelDetails.type = 2
          optionalModelDetails.formData.name = currentRow.value.name
          optionalModelDetails.show = true
        }
      }
    },
    {
      type: 'divider',
      key: 'd2',
      show: more,
    },
    {
      label: '更多',
      key: 'more',
      icon: renderIcon(MoreOutlined),
      show: more,
      children: [
        {
          label: '复制到',
          key: 'copyTo',
          icon: renderIcon(CopyOutlined),
          show: copyToShow,
          props: {
            onClick: async () => {
              optionalModelDetails.type = 3
              optionalModelDetails.formData.to = currentRow.value.fileParentFolder
              optionalModelDetails.show = true
              dirChangeOptions.value = [await getFolderList()]
              optionalModelDetails.formData.name = currentDirInfo.value.folder.name
            }
          }
        },
        {
          label: '移动到',
          key: 'moveTo',
          icon: renderIcon(VerticalLeftOutlined),
          show: moveToShow,
          props: {
            onClick: async () => {
              optionalModelDetails.type = 4
              optionalModelDetails.formData.to = currentRow.value.fileParentFolder
              optionalModelDetails.show = true
              dirChangeOptions.value = [await getFolderList()]
              optionalModelDetails.formData.name = currentDirInfo.value.folder.name
            }
          }
        },
        {
          type: 'divider',
          key: 'd3',
          show: (moveToShow || copyToShow) && deleteShow
        },
        {
          label: '删除',
          key: 'delete',
          icon: renderIcon(DeleteOutlined),
          show: deleteShow,
          props: {
            onClick: async () => {
              await dialog.warning({
                title: '警告',
                content: `确定对选中的文件进行删除？将会纳入回收站`,
                positiveText: '确定',
                negativeText: '取消',
                onPositiveClick: async () => {
                  await delete2Recycle([currentRow.value.id])
                  await toHashAndLoadingData()
                },
                onNegativeClick: () => { }
              })
            }
          }
        },
      ]
    },
    {
      label: '还原',
      key: 'restore',
      icon: renderIcon(UndoOutlined),
      show: recycleShow,
      props: {
        onClick: () => {
          dialog.info({
            title: '提示',
            content: `确定后将还原至 <<${currentRow.value.filePath}>>`,
            positiveText: '确定',
            negativeText: '取消',
            onPositiveClick: () => {
              recycleRestore([currentRow.value.id])
                .then(() => toHashAndLoadingData())
                .catch(() => dialog.destroyAll())
            },
            onNegativeClick: () => { }
          })
        },
      }
    },
    {
      label: '销毁',
      key: 'remove',
      icon: renderIcon(RestOutlined),
      show: recycleShow,
      props: {
        onClick: () => {
          dialog.warning({
            title: '警告',
            content: `销毁后将无法恢复，是否继续？`,
            positiveText: '继续',
            negativeText: '取消',
            onPositiveClick: () => {
              recycleDelete([currentRow.value.id])
                .then(() => toHashAndLoadingData())
                .catch(() => dialog.destroyAll())
            },
            onNegativeClick: () => { }
          })
        },
      }
    },
  ]
}
function fileSelect (key, option) {
  showFileDropdownRef.value = false;
}

// ------- 操作下拉框
const dirChangeOptions = ref<IFolder[]>([])
const optionalModelDetails = reactive({
  show: false,
  type: 0,
  title: ['新建文件夹', '修改文件夹', '文件重命名', '文件拷贝', '文件移动'],
  formData: {
    name: '',
    power: Power.PUBLIC,
    to: ''
  }
})
const handleUpdateValue = (value, option) => {
  optionalModelDetails.formData.to = value
}

// ------ 批量操作
const batchOptions = ref<any[]>([])
const generatorBatchOptions = () => {
  const copyAndMoveShow = isLogin.value && !isRecycle(showStatus.value);
  return [
    {
      label: '下载',
      key: 'download',
      icon: renderIcon(CloudDownloadOutlined),
      show: !isRecycle(showStatus.value),
      props: {
        onClick: () => {
          checkCheckedRowKeys()
          if (checkedRowKeys.value.length === 0) {
            return message.warning('请选择文件')
          }
          currentDirInfo.value.files.forEach(item => {
            if (checkedRowKeys.value.includes(item.id)) {
              handlerDownload(item)
            }
          })
        }
      }
    },
    {
      label: '复制到',
      key: 'copy',
      icon: renderIcon(CopyOutlined),
      show: copyAndMoveShow,
      props: {
        onClick: async () => {
          checkCheckedRowKeys()
          optionalModelDetails.type = 3
          optionalModelDetails.formData.to = currentRow.value.fileParentFolder
          optionalModelDetails.show = true
          dirChangeOptions.value = [await getFolderList()]
          optionalModelDetails.formData.name = currentDirInfo.value.folder.name
        }
      }
    },
    {
      label: '移动到',
      key: 'move',
      icon: renderIcon(MoveOutline),
      show: copyAndMoveShow,
      props: {
        onClick: async () => {
          checkCheckedRowKeys()
          optionalModelDetails.type = 4
          optionalModelDetails.formData.to = currentRow.value.fileParentFolder
          optionalModelDetails.show = true
          dirChangeOptions.value = [await getFolderList()]
          optionalModelDetails.formData.name = currentDirInfo.value.folder.name
        }
      }
    },
    {
      label: '删除',
      key: 'delete',
      icon: renderIcon(DeleteOutlined),
      show: isLogin.value && isUser(showStatus.value),
      props: {
        onClick: async () => {
          checkCheckedRowKeys()
          dialog.warning({
            title: '警告',
            content: `确定对选中的${checkedRowKeys.value.length}个文件删除？将会纳入回收站`,
            positiveText: '确定',
            negativeText: '取消',
            onPositiveClick: () => {
              delete2Recycle(checkedRowKeys.value)
                .then(() => toHashAndLoadingData())
                .catch(() => dialog.destroyAll())
            },
            onNegativeClick: () => { }
          })
        }
      }
    },
    {
      label: '还原',
      key: 'restore',
      icon: renderIcon(UndoOutlined),
      show: false/*isRecycle(showStatus.value)*/,
      props: {
        onClick: () => {
          // 暂时不进行批量还原
          checkCheckedRowKeys()
          dialog.info({
            title: '提示',
            content: `确定后将对${checkedRowKeys.value.length}个文件还原`,
            positiveText: '确定',
            negativeText: '取消',
            onPositiveClick: () => {
              recycleRestore(checkedRowKeys.value)
                .then(() => toHashAndLoadingData())
                .catch(() => dialog.destroyAll())
            },
            onNegativeClick: () => { }
          })
        }
      }
    },
    {
      label: '销毁',
      key: 'remove',
      icon: renderIcon(RestOutlined),
      show: isRecycle(showStatus.value),
      props: {
        onClick: async () => {
          checkCheckedRowKeys()
          dialog.warning({
            title: '警告',
            content: `将对${checkedRowKeys.value.length}个文件进行销毁，是否继续？`,
            positiveText: '继续',
            negativeText: '取消',
            onPositiveClick: () => {
              recycleDelete(checkedRowKeys.value)
                .then(() => toHashAndLoadingData())
                .catch(() => dialog.destroyAll())
            },
            onNegativeClick: () => { }
          })
        }
      }
    }
  ]
}

// ------- 文件夹 新建/更改, 文件 重命名/拷贝/移动
// 可批量操作处理器
const canBatchChangeHandler = async (callback: Function) => {
  let arr: string[] = []
  // 如果开启批量操作，那么自行封装批量操作的数据
  if (!checkedRowKeys.value.length) {
    // 单操作
    arr.push(currentRow.value.id)
  } else {
    Object.assign(arr, checkedRowKeys.value)
  }
  // 操作函数
  await callback(arr)
}
const optionSubmit = async () => {
  const name = optionalModelDetails.formData.name
  const power = optionalModelDetails.formData.power
  if (name === '') {
    return message.warning('信息未填写')
  }
  // 新建 文件夹
  if (optionalModelDetails.type === 0) {
    await createFolder({
      name, power, parentId: getCurrentDirId()
    })
  }
  // 更改 文件夹
  if (optionalModelDetails.type === 1) {
    if (currentRow.value.name === name && currentRow.value.power === power) {
      return message.warning('没改动就不提交哈')
    }
    await updateFolder({
      id: currentRow.value.id,
      name, power
    })
  }
  // 重命名 文件
  if (optionalModelDetails.type === 2) {
    if (currentRow.value.name === name) {
      return message.warning('没改动就不提交哈')
    }
    await fileRename({
      fileId: currentRow.value.id,
      name
    })
  }
  const to = optionalModelDetails.formData.to
  // 拷贝 文件
  if (optionalModelDetails.type === 3) {
    if (currentRow.value.fileParentFolder === to) {
      return message.warning('没改动就不提交哈')
    }
    await canBatchChangeHandler(async arr => {
      await fileCopyTo({
        fileIds: arr,
        dirId: to
      }).catch(e => optionalModelDetails.show = false)
    })
  }
  // 移动 文件
  if (optionalModelDetails.type === 4) {
    if (currentRow.value.fileParentFolder === to) {
      return message.warning('没改动就不提交哈')
    }
    await canBatchChangeHandler(async arr => {
      await fileMoveTo({
        fileIds: arr,
        dirId: to
      }).catch(e => optionalModelDetails.show = false)
    })
  }
  optionalModelDetails.show = false
  await toHashAndLoadingData()
}

// ------- 文件夹 权限
const dirPowerOptions = ref<any[]>([])
watch(() => optionalModelDetails.show, (value) => {
  if (value) {
    dirPowerOptions.value = generatorDirPowerOptions()
  }
}, { deep: true })
const generatorDirPowerOptions = () => {
  let disable = false;
  // 新建文件夹
  if (optionalModelDetails.type === 0) {
    disable = currentDirInfo.value.folder.power !== Power.COMMON;
  }
  // 更改文件夹
  if (optionalModelDetails.type === 1) {
    disable = false
  }
  return [
    {
      label: '公共',
      value: Power.COMMON,
      disabled: disable
    },
    {
      label: '公开',
      value: Power.PUBLIC,
      disabled: currentDirInfo.value.folder.power === Power.COMMON
    },
    {
      label: '私有',
      value: Power.PRIVATE,
      disabled: currentDirInfo.value.folder.power === Power.COMMON
    }
  ]
}
</script>

<style lang="less" scoped>
.fs-container {
  user-select: none;

  .left-container {
    .title {
      font-size: 16px;
      text-align: center;
      font-weight: bold;
      padding: 10px 0;
    }

    .dir-list {
      ::v-deep(.n-tabs.n-tabs--left) {
        flex-direction: column;
      }
    }
  }

  .right-container {
    flex: 1;

    .title {
      padding: 5px 0;
      box-sizing: border-box;
    }

    .expansion {
      padding: 5px 0;
      box-sizing: border-box;
    }

    .content {
      padding-top: 5px;
    }
  }
}

#upload-btn {
  display: none;
}

.menu-bar {
  position: fixed;
  border:  1px solid #ccc;
  background-color: #f7f7f7;
}

.file_load_list_btn {
  font-size: 18px;
  position: fixed;
  right: 25px;
  bottom: 20px;
}

.file-list-card {
  position: relative;
  width: 500px;
  height: 200px;
  overflow-y: auto;

  .file-list-ul {
    overflow-y: hidden;
    list-style: none;
    padding: 0;
    margin: 0;

    .download-li {
      height: 50px;
      display: flex;
      flex-direction: row;
      justify-content: space-between;
      border-bottom: 1px solid rgb(239, 239, 245);
    }

    .download-li:hover {
      background-color: rgba(0, 0, 0, .09);
    }

    :deep(.uploader-file > .uploader-file-info) {
      .uploader-file-actions > span {
        margin-right: 6px;
      }
    }
  }

  .no-file {
    text-align: center;
    height: 100%;
    display: flex;
    justify-content: center;
    flex-direction: column;
  }
}
</style>
